#include "tvOpenCV_ImageIO.h"
#include "tvRawImageIO.h"
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>

bool TvOpenCV_ImageIO::writePGM(char *file_out_name, IplImage * src, const bool bigEndian )
{
	// Set up variables
	TvImageSize tempSize;

	// Write image if it exists
	if (src)
	{
		if(src->depth == IPL_DEPTH_8U)
			tempSize.setImage(src->width,src->height,TV_DATATYPE_8U);
		else if(src->depth == IPL_DEPTH_16U)
			tempSize.setImage(src->width,src->height,TV_DATATYPE_16U);
		else
			return true;

		return rawIO.writePGM(file_out_name, tempSize, (char*) src->imageData, bigEndian);
	}
	else
		return true;
}

IplImage * TvOpenCV_ImageIO::loadPGM(char *file_in_name, const bool bigEndian)
{
	TvImageSize tempSize;

	IplImage * tempImg = NULL;

	// Get image data
	char * outputData = rawIO.loadPGM(file_in_name, tempSize, bigEndian);

	// If data returned
	if(outputData)
	{
		// Create image
		tempImg = cvCreateImage(
			cvSize(tempSize.width,tempSize.height),
			getIplDepth(tempSize),
			1 );

		// Copy image data to image
		char * tempData = (char*) tempImg->imageData;
		char * tempOutput = outputData;
		for (int y = 0 ; y < tempSize.getNumberBytes() ; y++, tempData++, tempOutput++)
			*tempData = *tempOutput;

		delete [] outputData;
		return tempImg;
	}
	else
	{
		return NULL;
	}
}

IplImage * TvOpenCV_ImageIO::loadPPM(char *file_in_name, const bool bigEndian)
{
	TvImageSize tempSize;

	IplImage * tempImg = NULL;

	// Get image data
	char * outputData = rawIO.loadPPM(file_in_name, tempSize, bigEndian);

	// If data returned
	if(outputData)
	{
		// Create image
		tempImg = cvCreateImage(
			cvSize(tempSize.width,tempSize.height),
			getIplDepth(tempSize),
			3 );

		// Copy image data to image
		tempImg->imageData = outputData;
		tempImg->colorModel[0] = 'R';
		tempImg->colorModel[1] = 'G';
		tempImg->colorModel[2] = 'B';

		cvCvtColor(tempImg,tempImg,CV_RGB2BGR);

		return tempImg;
	}
	else
	{
		return NULL;
	}
}


bool TvOpenCV_ImageIO::loadPGM(char *file_in_name, IplImage * src, const bool bigEndian)
{
	// Makes sure it is not NULL
	if (src == NULL)
		return true;

	// Set up variables
	TvImageSize tempSize;
	bool error;

	// Set image size
	error= setImageSize(src,tempSize);
	if (error)
	{
		std::cout << "Image type not supported\n";
		return true;
	}

	// Load image
	error = rawIO.loadPGM(file_in_name, tempSize, (char*) src->imageData, bigEndian);

	if (error)
		return true;
	else
		return false;

}


bool TvOpenCV_ImageIO::loadRawDataImage(char *file_in_name, IplImage * src)
{
	// Makes sure it is not NULL
	if (src == NULL)
		return true;

	// Set up variables
	TvImageSize tempSize;
	bool error;

	// Set image size
	error= setImageSize(src,tempSize);
	if (error)
	{
		std::cout << "Image type not supported\n";
		return true;
	}

	// Load image
	error = rawIO.loadRawDataImage(file_in_name, tempSize, (char*) src->imageData);

	if (error)
		return true;
	else
		return false;

	return NULL;
}

IplImage * TvOpenCV_ImageIO::loadRawDataImage(char *file_in_name)
{
	TvImageSize tempSize;
	IplImage * tempImg = NULL;

	// Get image data
	char * outputData = rawIO.loadRawDataImage(file_in_name, tempSize);

	// If data returned
	if(outputData)
	{
		// Create image
		tempImg = cvCreateImage(
			cvSize(tempSize.width,tempSize.height),
			getIplDepth(tempSize),
			1 );

		// Copy image data to image
		char * tempData = (char*) tempImg->imageData;
		char * tempOutput = outputData;
		for (int y = 0 ; y < tempSize.getNumberBytes() ; y++, tempData++, tempOutput++)
			*tempData = *tempOutput;

		delete [] outputData;
		return tempImg;
	}
	else
	{
		return NULL;
	}
}



bool TvOpenCV_ImageIO::writeRawDataImage(
	char *file_out_name,
	IplImage * src,
	char * comments )
{
	TvImageSize tempSize;
	bool error;


	// If an image exists then write the image
	if (src)
	{
		error = setImageSize(src,tempSize);
		if (error)
			return true;
		else
			return rawIO.writeRawDataImage(file_out_name, tempSize, (char*)src->imageData, comments);
	}
	else
		return true;
}


bool TvOpenCV_ImageIO::setImageSize(IplImage* src, TvImageSize & imageSize)
{
	if(src == NULL)
		return true;

	if(src->depth == IPL_DEPTH_8U)
		imageSize.setImage(src->width,src->height,TV_DATATYPE_8U);
	else if(src->depth == IPL_DEPTH_8S)
		imageSize.setImage(src->width,src->height,TV_DATATYPE_8S);
	else if(src->depth == IPL_DEPTH_16U)
		imageSize.setImage(src->width,src->height,TV_DATATYPE_16U);
	else if(src->depth == IPL_DEPTH_16S)
		imageSize.setImage(src->width,src->height,TV_DATATYPE_16S);
	else if(src->depth == IPL_DEPTH_32F)
		imageSize.setImage(src->width,src->height,TV_DATATYPE_32F);
	else if(src->depth == IPL_DEPTH_64F)
		imageSize.setImage(src->width,src->height,TV_DATATYPE_64F);
	else
		return true;

	return false;
}

int TvOpenCV_ImageIO::getIplDepth(TvImageSize & imageSize)
{
	if(imageSize.dataType == TV_DATATYPE_8U)
		return IPL_DEPTH_8U;
	else if(imageSize.dataType == TV_DATATYPE_8S)
		return IPL_DEPTH_8S;
	else if(imageSize.dataType == TV_DATATYPE_16U)
		return IPL_DEPTH_16U;
	else if(imageSize.dataType == TV_DATATYPE_16S)
		return IPL_DEPTH_16S;
	else if(imageSize.dataType == TV_DATATYPE_32F)
		return IPL_DEPTH_32F;
	else if(imageSize.dataType == TV_DATATYPE_64F)
		return IPL_DEPTH_64F;
	else
		return 0;
}
